package com.link.base.base.orgnization.controller;

import com.link.base.base.orgnization.UpdateOrganization;
import com.link.base.base.orgnization.model.LinkTable;
import com.link.base.base.orgnization.model.Orgnization;
import com.link.base.base.orgnization.service.OrgnizationService;
import com.link.base.base.system.utils.RunOrgUpdate;
import com.link.base.base.system.utils.TreeUtil;
import com.link.base.core.basic.util.ThreadPoolExecutorSingleton;
import com.link.base.user.model.CoreUser;
import com.link.core.basic.annotations.JsonParam;
import com.link.core.basic.controller.BasicController;
import com.link.core.basic.model.BasicModel;
import com.link.core.basic.model.CallParam;
import com.link.core.basic.query.Filter;
import com.link.core.basic.query.QueryParams;
import com.link.core.basic.query.Sorter;
import com.link.core.basic.service.BasicService;
import com.link.core.basic.service.ServiceException;
import com.link.core.cllog.LCLogger;
import com.link.core.util.RedisUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.UserUtil;
import com.link.core.util.redisclient.LinkRedisClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author unknown
 * @date unknown
 * @comments 组织树操作请求处理
 */
@Controller
@RequestMapping("/link/orgnization")
public class OrgnizationController extends BasicController<Orgnization> {
    @Resource
    private OrgnizationService orgnizationService;

    @Override
    public BasicService<Orgnization> getBasicService() throws Exception {
        return orgnizationService;
    }

    /**
     * 加载树
     */
    @RequestMapping(value = "/treelist", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> treelist(QueryParams qps, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            Orgnization root = orgnizationService.queryRoot(new Orgnization());
            orgnizationService.queryTreeByRoot(root);
            result.put("success", true);
            result.put("tree", true);
            //传根节点
            result.put("list", root);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("list", new Orgnization());
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 加载结构框图树
     */
    @RequestMapping(value = "/treelist/{initOrgId}")
    @ResponseBody
    public Orgnization treelist(@PathVariable Long initOrgId, QueryParams qps, HttpSession session,
                                HttpServletRequest request, HttpServletResponse response) {
        Orgnization root = new Orgnization();
        try {
            root.setId(initOrgId);
            root = orgnizationService.queryById(root);
            orgnizationService.queryTreeByRoot1(root);
        } catch (Exception e) {
            LCLogger.withException(e);
        }
        return root;
    }

    /**
     * 选择父对象时的picklist
     */
    @RequestMapping(value = "/parentPicklist", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> parentPicklist(@JsonParam Orgnization entity, @JsonParam QueryParams qps, HttpSession session,
                                              HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            //按创建时间来排序
            qps.addSorter(new Sorter("created", Sorter.DIR_DESC));
            String flag = "Y";
            if (StringUtils.equals(qps.getAttr1(), flag)) {
                //如果是组织
                qps.addFilter(new Filter("isOrg", qps.getAttr1()));
            }
            Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, qps);
            t.preDealSecurity(request);
            List<Orgnization> list = orgnizationService.queryListRemoveIdAndChildrenPage(t);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", getCount(((BasicModel) t), list.size()));
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("rows", new ArrayList<Orgnization>());
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 通用picklist
     */
    @RequestMapping(value = "/picklist", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> picklist(QueryParams qps, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, qps);
            t.preDealSecurity(request);
            List<Orgnization> list = orgnizationService.queryByExamplePage(t);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", getCount(((BasicModel) t), list.size()));
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("rows", new ArrayList<Orgnization>());
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 根据ID删除该记录以及其子对象
     */
    @RequestMapping(value = "/deleteWithChildById")
    @ResponseBody
    public Map<String, Object> deleteWithChildById(@JsonParam Orgnization entity, HttpSession session,
                                                   HttpServletRequest request, HttpServletResponse response) {
        LCLogger.info().withMessageKey("deleteWithChildById")
                .withMessage("根据ID删除该记录以及其子对象信息...").flush();
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            beforDelete(entity, request);
            checkData(entity, request);
            String base = "base";
            if (!checkExistDataCache( base, session, entity)) {
                throw new ServiceException("PUBLIC-031");
            }
            //审计追踪新建记录
            //auditTrailInsert(entity, request, session, "D");
            orgnizationService.deleteWithChildById(entity);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * desc 异步线程更新组织架构
     *
     * @author libo
     * @date   2019-07-12
     * @param
     */
    @RequestMapping(value = "/run", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> run(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        LinkRedisClient jedis = null;
        String key = "";
        try {
            //设置一个key,有效期为30分钟，标记当前是否有人正在更新当前帐套，当正常更新完则销毁，否则抛出异常正在有人更新
            jedis = RedisUtil.getJedis();
            key = "updateOrg_" + UserUtil.getUser().getCorpid();
            jedis.expire(key, 60 * 30);
            boolean flag = jedis.exists(key);
            if (flag && "loading".equalsIgnoreCase(jedis.get(key))) {
                throw new Exception("当前组织架构正在有您或其他人更新，请等待!");
            }
            jedis.set(key, "loading");
            CallParam callParam = new CallParam();
            Long corpId = null;
            CoreUser user = UserUtil.getUser();
            if (user != null && null != user.getCorpid()) {
                corpId = user.getCorpid();
            }
            if (null == corpId) {
                throw new ServiceException("PUBLIC-044");
            }
            callParam.setParam1(corpId);
            ExecutorService threadExecutor = ThreadPoolExecutorSingleton.getInstance();
            threadExecutor.execute(new UpdateOrganization(callParam, key));
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 新版更新组织、职位、部门结构
     * 更新拉平表lnk_party_rel表中的数据
     *
     * @author LiYang
     * @date 2019/12/13
     * @param
     */
    @RequestMapping(value = "/runNew", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> runNew(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>();
        LinkRedisClient jedis = null;
        try {
            //这里同步更新组织、部门、职位。如果想要进一步提高速度可考虑使用异步的方法调用3次这个方法
//            orgnizationService.runOrgUpdateNew("ORG");
//            orgnizationService.runOrgUpdateNew("DEPT");
//            orgnizationService.runOrgUpdateNew("POSTN");

            /*
             * @mark LiYang 2019/12/16
             * @update 使用线程分别构建组织、部门、职位结构。
             * 这里只是简单的用缓存限制了一下更新频率，如想获得确切的更新结果时间，请考虑使用Callable等方式改造
             * 经粗略测试，5W~5W1个节点的拉平表对应的hash大概34M左右，并行执行更新组织、部门、职位较差情况大概需要100M+的内存
             * 如果数据更大，建议使用上面注释掉的方法，启用顺序执行
             */
            jedis = RedisUtil.getJedis();
            String value = jedis.get(TreeUtil.UPDATE_ORG_LOCK_KEY);
            if ("lock".equals(value)) {
                result.put("success", false);
                result.put("result", "正在更新中，请稍后再试...");
                return result;
            }
            jedis.set(TreeUtil.UPDATE_ORG_LOCK_KEY, "lock");
            //30秒内只允许执行一次更新
            jedis.expire(TreeUtil.UPDATE_ORG_LOCK_KEY, 30);
            //使用线程更新组织、部门、职位结构
            ThreadPoolExecutor executor = ThreadPoolExecutorSingleton.getInstance();
            CoreUser user = UserUtil.getUser();
            executor.execute(new RunOrgUpdate("ORG", user));
            executor.execute(new RunOrgUpdate("DEPT", user));
            executor.execute(new RunOrgUpdate("POSTN", user));
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    @RequestMapping(value = "/companyList", method = RequestMethod.POST)
    @ResponseBody
    public List<Orgnization> companyList(QueryParams qps, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        List<Orgnization> list = null;
        qps.parseFromRaw();
        /*//按创建时间来排序
        Sorter sorter = new Sorter("created",Sorter.DIR_DESC);
        qps.addSorter(sorter);*/
        try {
            Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, qps);
            list = orgnizationService.queryCompanyInOrgnizationSelect(t);
        } catch (Exception e) {
            LCLogger.withException(e);
        }
        return list;
    }

    @RequestMapping(value = "/queryTableInfoList", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> queryTableInfoList(LinkTable entity, QueryParams qps,
                                                  HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            entity.setPageFlag(false);
            entity = (LinkTable) BasicModel.transformClass(entity.getClass(),qps);
            if (entity.getQps() != null) {
                entity.getQps().getFilters().forEach(f -> {
                    f.setProperty(f.getProperty().replace("`", ""));
                });
                System.out.println(entity.getQps().toString());
            }
            List<LinkTable> list = orgnizationService.queryTableInfoList(entity);
            result.put("success", true);
            result.put("rows", list);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    @RequestMapping(value = "/queryColInfoListByTableName", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> queryColInfoListByTableName(LinkTable entity,QueryParams qps,
                                                           HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            LinkTable record = (LinkTable) BasicModel.transformClass(entity.getClass(),qps);
            record.setTableName(entity.getTableName());
            if (record.getQps() != null) {
                record.getQps().getFilters().forEach(f -> {
                    f.setProperty(f.getProperty().replace("`", ""));
                });
            }
            List<LinkTable> list = orgnizationService.queryColInfoListByTableName(record);
            result.put("success", true);
            result.put("rows", list);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    @RequestMapping(value = "/saveCombineOrg", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> saveCombineOrg(@RequestBody LinkTable entity,
                                              HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            orgnizationService.saveCombineOrg(entity);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 获取组织树，其中树包含根结点，且只含有有效的组织
     * @author 姚江漪
     * @date 2019/05/14 10:19
     */

    @RequestMapping(value = "/treelistContainRoot", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> treelistContainRoot(QueryParams qps, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            CoreUser user = UserUtil.getUser();
            Orgnization orgnization = new Orgnization();
            if ("MY_ORG".equals(qps.getOauth())) {
                orgnization.setOrgId(user.getOrgId());
            }
            orgnization = (Orgnization) BasicModel.transformClass(orgnization, qps);
            Orgnization root = orgnizationService.queryRoot(orgnization);
            orgnizationService.queryTreeByRoot2(root);
            result.put("success", true);
            result.put("tree", true);
            //传根节点
            result.put("list", root);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("list", new Orgnization());
            result.put("result", e.getMessage());
        }
        return result;
    }
}
